package com.wtwd.campus.vcom.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.entity.LastLocationData;
import com.wtwd.campus.entity.LocationDataVo;
import com.wtwd.campus.entity.LocationSubmeter;
import com.wtwd.campus.service.DeviceFlagService;
import com.wtwd.campus.service.LastLocationDataService;
import com.wtwd.campus.service.LocationSubmeterService;
import com.wtwd.campus.utils.DateUtils;
import com.wtwd.campus.vcom.common.*;
import com.wtwd.campus.vcom.entity.*;
import com.wtwd.campus.vcom.entity.vo.VcomRequestVo;
import com.wtwd.campus.vcom.service.RequestRecordService;
import com.wtwd.campus.vcom.service.ValidService;
import com.wtwd.campus.vcom.service.VcomDeviceInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: ldaoliang
 * @DateTime: 2022/1/4 10:13
 * @Description:
 */
@Api(tags = "设备模块")
@RestController
@RequestMapping("/vcom/device/")
public class VcomDeviceController {

    private static final Logger logger = LoggerFactory.getLogger(VcomDeviceController.class);

    @Autowired
    private ValidService validService;
    @Autowired
    private VcomDeviceInfoService vcomDeviceInfoService;
    @Autowired
    private RequestRecordService requestRecordService;
    @Autowired
    private LastLocationDataService lastLocationDataService;
    @Autowired
    private DeviceFlagService deviceFlagService;
    @Autowired
    private LocationSubmeterService locationSubmeterService;

    @Autowired
    private static ExecutorService pool = Executors.newSingleThreadExecutor();

    /**
     * TODO 待确定请求头部携带的token的key是  AccessToken 还是  Access-Token（目前按照这个为准）
     * 获取设备最新的定位数据
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("/getDeviceLatestLocation")
    public RespEntity getDeviceLatestLocation(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        String imei = jsonObject.getString("imei");
        logger.info("/getDeviceLatestLocation,body={}", jsonObject.toString());
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        RespCode validResult = validService.validSingleDevice(token, imei);
        if (validResult.getCode() != RespCode.SUCCESS.getCode()) {
            return new RespEntity(validResult);
        }
        LocationDataVo locationData = vcomDeviceInfoService.getDeviceLatestLocation(imei);
        return new RespEntity(RespCode.SUCCESS, locationData);
    }

    /**
     * 设置亲情号码、白名单、sos号码
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/setFamilyNoAndWhiteList")
    public ResponseEntity setFamilyNoAndWhiteList(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("/setFamilyNoAndWhiteList,body={}", jsonObject.toString());
        String imei = jsonObject.getString("imei");
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        RespCode validResult = validService.validSingleDevice(token, imei);
        if (validResult.getCode() != RespCode.SUCCESS.getCode()) {
            return new ResponseEntity(validResult, false, null);
        }
        String action = jsonObject.getString("action");
        String commandValue = jsonObject.getString("commandValue");
        return vcomDeviceInfoService.setPhoneData(action, commandValue, imei);
    }


    /**
     * 获取亲情号和白名单列表
     *
     * @param data
     * @param request
     * @return
     */
    @PostMapping("/getAllTypePhone")
    public RespEntity getFamilyNoAndWhiteList(@RequestBody JSONObject data, HttpServletRequest request) {
        logger.info("/getFamilyNoAndWhiteList,body={}", data.toString());
        String imei = data.getString("imei");
        if (StringUtils.isBlank(imei)) {
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        List<VcomPhoneData> phoneList = vcomDeviceInfoService.getPhoneDataByImei(imei);
        Map<String, Object> result = new HashMap<>();
        result.put("imei", imei);
        Map<String, Object> phone = new HashMap<>();
        phoneList.stream().forEach(e -> {
            String phoneData = "";
            if (e.getStatus() == Constant.PHONE_STATUS_NORMAL) {
                phoneData = e.getPhoneData() == null ? "" : e.getPhoneData();
            } else {
                phoneData = e.getOldData() == null ? "" : e.getOldData();
            }
            JSONArray phoneArray = JSONObject.parseArray(phoneData);
            if (phoneArray != null) {
                if (e.getType() == Constant.PHONE_SOS) {
                    //处理SOS号码
                    JSONObject sos = (JSONObject) phoneArray.get(0);
                    Map<String, Object> sosMap = new HashMap<>();
                    sosMap.put("relationship", sos.getString("name"));
                    sosMap.put("phone", sos.getString("phone"));
                    phone.put("sos", sosMap);
                } else if (e.getType() == Constant.PHONE_FAMILY) {
                    //处理亲情号码
                    List<Map<String, Object>> familyList = new ArrayList<>();
                    phoneArray.stream().forEach(f -> {
                        JSONObject familyNo = (JSONObject) f;
                        if (!StringUtils.isBlank(familyNo.getString("phone"))) {
                            Map<String, Object> familyMap = new HashMap<>();
                            familyMap.put("relationship", familyNo.getString("name"));
                            familyMap.put("phone", familyNo.getString("phone"));
                            familyMap.put("pressKey", familyNo.getInteger("sequence") - 3);
                            familyList.add(familyMap);
                        }
                    });
                    phone.put("familyNoList", familyList);
                } else if (e.getType() == Constant.PHONE_WHITE) {
                    //处理白名单号码
                    List<Map<String, Object>> whiteList = new ArrayList<>();
                    phoneArray.stream().forEach(w -> {
                        JSONObject whiteNo = (JSONObject) w;
                        if (!StringUtils.isBlank(whiteNo.getString("phone"))) {
                            Map<String, Object> whiteMap = new HashMap<>();
                            whiteMap.put("relationship", whiteNo.getString("name"));
                            whiteMap.put("phone", whiteNo.getString("phone"));
                            whiteList.add(whiteMap);
                        }
                    });
                    phone.put("whiteList", whiteList);
                }
            }
        });
        result.put("item", phone);
        return new RespEntity(RespCode.SUCCESS, result);
    }

    /**
     * 下发学习通知
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/sendLearnNotice")
    public ResponseEntity sendLearnNotice(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("/sendLearnNotice,body={}", jsonObject.toString());
        String imei = jsonObject.getString("imei");
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        RespCode validResult = validService.validSingleDevice(token, imei);
        if (validResult.getCode() != RespCode.SUCCESS.getCode()) {
            return new ResponseEntity(validResult, false, null);
        }
        // 保存请求id
        RequestId requestId = requestRecordService.saveRequestRecord(imei, jsonObject.toJSONString(), Constant.COMMAND_TYPE_MESSAGE);
        if (!requestId.isSuccess()) {
            return new ResponseEntity(RespCode.REQUEST_DEAL_ERROR, false, null);
        }
        // 判断当前条是否需要发送（该设备该类型是否有未完成的，如果没有则查询是否最老的一条未发送的进行发送）
        VcomRequestRecord nextSendCommand = requestRecordService.getNextSendCommand(imei, requestId.getRequestId(), Constant.COMMAND_TYPE_MESSAGE);
        if (nextSendCommand == null) {
            return new ResponseEntity(RespCode.WAITING_SEND, true, requestId.getRequestId());
        } else {
            return vcomDeviceInfoService.sendMessage(nextSendCommand);
        }
    }

    /**
     * 批量下发消息
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/batchSendMessage")
    public ResponseEntity batchSendLearnNotice(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("/batchSendLearnNotice,body={}", jsonObject.toString());
        JSONArray imeis = jsonObject.getJSONArray("imeis");
        List<String> imeiList = imeis.toJavaList(String.class);
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        Object validResult = validService.validImeiList(token, imeiList);
        if (validResult instanceof RespCode) {
            return new ResponseEntity((RespCode) validResult, false, null);
        }
        List<String> resultImeiList = (List<String>) validResult;
        String requestData = jsonObject.toJSONString();
        RequestId requestId = requestRecordService.batchCommandSaveRequest(resultImeiList, requestData, Constant.COMMAND_TYPE_MESSAGE);
        if (!requestId.isSuccess()) {
            return new ResponseEntity(RespCode.REQUEST_DEAL_ERROR, false, null);
        }
        // 线程池处理
        pool.submit(() -> {
            for (String imei : resultImeiList) {
                // 判断当前条是否需要发送（该设备该类型是否有未完成的，如果没有则查询是否最老的一条未发送的进行发送）
                VcomRequestRecord nextSendCommand = requestRecordService.getNextSendCommand(imei, requestId.getRequestId(), Constant.COMMAND_TYPE_MESSAGE);
                if (nextSendCommand != null) {
                    vcomDeviceInfoService.sendMessage(nextSendCommand);
                }
            }
        });
        return new ResponseEntity(RespCode.TASK_DOING, true, requestId.getRequestId());
    }

    /**
     * 发送短消息
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/sendShortMessage")
    public ResponseEntity sendShortMessage(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("/sendShortMessage,body={}", jsonObject.toString());
        String imei = jsonObject.getString("imei");
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        RespCode validResult = validService.validSingleDevice(token, imei);
        if (validResult.getCode() != RespCode.SUCCESS.getCode()) {
            return new ResponseEntity(validResult, false, null);
        }
        // 保存请求id
        RequestId requestId = requestRecordService.saveRequestRecord(imei, jsonObject.toJSONString(), Constant.COMMAND_TYPE_SHORT_MESSAGE);
        if (!requestId.isSuccess()) {
            return new ResponseEntity(RespCode.REQUEST_DEAL_ERROR, false, null);
        }
        // 判断当前条是否需要发送（该设备该类型是否有未完成的，如果没有则查询是否最老的一条未发送的进行发送）
        VcomRequestRecord nextSendCommand = requestRecordService.getNextSendCommand(imei, requestId.getRequestId(), Constant.COMMAND_TYPE_SHORT_MESSAGE);
        if (nextSendCommand == null) {
            return new ResponseEntity(RespCode.WAITING_SEND, true, requestId.getRequestId());
        } else {
            return vcomDeviceInfoService.sendShortMessage(nextSendCommand);
        }
    }

    /**
     * 批量发送短消息
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/batchSendShortMessage")
    public ResponseEntity batchSendShortMessage(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("batchSendShortMessage,body={}", jsonObject.toString());
        JSONArray imeis = jsonObject.getJSONArray("imeis");
        List<String> imeiList = imeis.toJavaList(String.class);
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        Object validResult = validService.validImeiList(token, imeiList);
        if (validResult instanceof RespCode) {
            return new ResponseEntity((RespCode) validResult, false, null);
        }
        List<String> resultImeiList = (List<String>) validResult;
        String requestData = jsonObject.toJSONString();
        RequestId requestId = requestRecordService.batchCommandSaveRequest(resultImeiList, requestData, Constant.COMMAND_TYPE_SHORT_MESSAGE);
        if (!requestId.isSuccess()) {
            return new ResponseEntity(RespCode.REQUEST_DEAL_ERROR, false, null);
        }
        // 线程池处理
        pool.submit(() -> {
            for (String imei : resultImeiList) {
                // 判断当前条是否需要发送（该设备该类型是否有未完成的，如果没有则查询是否最老的一条未发送的进行发送）
                VcomRequestRecord nextSendCommand = requestRecordService.getNextSendCommand(imei, requestId.getRequestId(), Constant.COMMAND_TYPE_SHORT_MESSAGE);
                if (nextSendCommand != null) {
                    vcomDeviceInfoService.sendShortMessage(nextSendCommand);
                }
            }
        });
        return new ResponseEntity(RespCode.TASK_DOING, true, requestId.getRequestId());
    }

    /**
     * 设置免打扰
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/setNotDisturb")
    public ResponseEntity setNotDisturb(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("setNotDisturb,body={}", jsonObject.toString());
        String imei = jsonObject.getString("imei");
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        RespCode validResult = validService.validSingleDevice(token, imei);
        if (validResult.getCode() != RespCode.SUCCESS.getCode()) {
            return new ResponseEntity(validResult, false, null);
        }
        // 保存请求id
        RequestId requestId = requestRecordService.saveRequestRecord(imei, jsonObject.toJSONString(), Constant.COMMAND_TYPE_NOT_DISTURB);
        if (!requestId.isSuccess()) {
            return new ResponseEntity(RespCode.REQUEST_DEAL_ERROR, false, null);
        }
        // 判断当前条是否需要发送（该设备该类型是否有未完成的，如果没有则查询是否最老的一条未发送的进行发送）
        logger.info("/威科姆免打扰查询参数：imei={},requestId={},type={}", imei, requestId.getRequestId(), Constant.COMMAND_TYPE_NOT_DISTURB);
        VcomRequestRecord nextSendCommand = requestRecordService.getNextSendCommand(imei, requestId.getRequestId(), Constant.COMMAND_TYPE_NOT_DISTURB);
        logger.info("/nextSendCommand是否为空 :flag={}", nextSendCommand == null);
        if (nextSendCommand == null) {
            return new ResponseEntity(RespCode.WAITING_SEND, true, requestId.getRequestId());
        } else {
            logger.info("免打扰nextSendCommand:data={}", nextSendCommand.toString());
            return vcomDeviceInfoService.setNotDisturbData(nextSendCommand);
        }
    }

    /**
     * 批量设置免打扰
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/batchSetNotDisturb")
    public ResponseEntity batchSetNotDisturb(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("batchSetNotDisturb,body={}", jsonObject.toString());
        JSONArray imeis = jsonObject.getJSONArray("imeis");
        List<String> imeiList = imeis.toJavaList(String.class);
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        Object validResult = validService.validImeiList(token, imeiList);
        if (validResult instanceof RespCode) {
            return new ResponseEntity((RespCode) validResult, false, null);
        }
        List<String> resultImeiList = (List<String>) validResult;
        String requestData = jsonObject.toJSONString();
        RequestId requestId = requestRecordService.batchCommandSaveRequest(resultImeiList, requestData, Constant.COMMAND_TYPE_NOT_DISTURB);
        if (!requestId.isSuccess()) {
            return new ResponseEntity(RespCode.REQUEST_DEAL_ERROR, false, null);
        }
        // 线程池处理
        pool.submit(() -> {
            for (String imei : resultImeiList) {
                // 判断当前条是否需要发送（该设备该类型是否有未完成的，如果没有则查询是否最老的一条未发送的进行发送）
                VcomRequestRecord nextSendCommand = requestRecordService.getNextSendCommand(imei, requestId.getRequestId(), Constant.COMMAND_TYPE_NOT_DISTURB);
                if (nextSendCommand != null) {
                    vcomDeviceInfoService.setNotDisturbData(nextSendCommand);
                }
            }
        });
        return new ResponseEntity(RespCode.TASK_DOING, true, requestId.getRequestId());
    }


    /**
     * 批量查询定位(单次查询设备一次最多2000个)
     *
     * @param bathQueryDeviceLastLocationDto
     * @return
     */
    @ApiOperation(value = "批量查询定位(单次查询设备一次最多2000个)", notes = "")
    @PostMapping("/bathQueryDeviceLastLocation")
    public RespEntity bathQueryDeviceLastLocation(@RequestBody BathQueryDeviceLastLocationDto bathQueryDeviceLastLocationDto, HttpServletRequest request) {
        logger.info("bathQueryDeviceLastLocation,bathQueryDeviceLastLocationDto={}", bathQueryDeviceLastLocationDto.toString());
        List<String> imeis = bathQueryDeviceLastLocationDto.getImeis();
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        Object validResult = validService.validImeiList(token, imeis);
        if (validResult instanceof RespCode) {
            return new RespEntity((RespCode) validResult);
        }
        imeis = (List<String>) validResult;
        if (imeis == null || imeis.size() == 0 || imeis.size() > BathQueryDeviceLastLocationDto.maxImeis) {
            return new RespEntity(RespCode.IMEIS_NUM_ERROR);
        }
        List<LastLocationData> lastLocationData = lastLocationDataService.queryLastLocationDataByImeis(imeis);
        List<BathQueryDeviceLastLocationVo> bathQueryDeviceLastLocationVos = new ArrayList<>();
        if (lastLocationData != null && lastLocationData.size() > 0) {
            for (LastLocationData lastLocationDatum : lastLocationData) {
                BathQueryDeviceLastLocationVo bathQueryDeviceLastLocationVo = new BathQueryDeviceLastLocationVo();
                bathQueryDeviceLastLocationVo.setAddress(lastLocationDatum.getAddress());
                bathQueryDeviceLastLocationVo.setDeviceImei(lastLocationDatum.getDeviceImei());
                bathQueryDeviceLastLocationVo.setLatitude(lastLocationDatum.getLatitude());
                bathQueryDeviceLastLocationVo.setLongitude(lastLocationDatum.getLongitude());
                bathQueryDeviceLastLocationVo.setLocationTime(DateUtils.format(new Date(lastLocationDatum.getLocationTime()), DateUtils.dateFormat4));
                bathQueryDeviceLastLocationVo.setLocationType(lastLocationDatum.getLocationType());
                bathQueryDeviceLastLocationVos.add(bathQueryDeviceLastLocationVo);
            }
        }
        return new RespEntity(RespCode.SUCCESS, bathQueryDeviceLastLocationVos);
    }

    /**
     * 批量获取设备是否在线
     *
     * @param data
     * @param request
     * @return
     */
    @ApiOperation(value = "批量查询设备是否在线(单次查询设备一次最多2000个)", notes = "")
    @PostMapping("/queryDeviceIsOnline")
    public RespEntity queryDeviceIsOnline(@RequestBody Imeis data, HttpServletRequest request) {
        logger.info("queryDeviceIsOnline,imeis={}", data.toString());
        List<String> imeis = data.getImeis();
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        Object validResult = validService.validImeiList(token, imeis);
        if (validResult instanceof RespCode) {
            return new RespEntity((RespCode) validResult);
        }
        imeis = (List<String>) validResult;
        if (imeis == null || imeis.size() == 0 || imeis.size() > data.maxImeis) {
            return new RespEntity(RespCode.IMEIS_NUM_ERROR);
        }
        Map<String, Boolean> stringBooleanMap = deviceFlagService.bathGetDeviceOnline(imeis);
        return new RespEntity(RespCode.SUCCESS, stringBooleanMap);
    }

    /**
     * 通过imei,起始时间查询设备轨迹
     *
     * @param imei
     * @param startTime
     * @param endTime
     * @param request
     * @return
     */
    @ApiOperation(value = "通过imei,起始时间查询设备轨迹", notes = "起始时间必填")
    @GetMapping("/queryDeviceTrajectory")
    public RespEntity queryDeviceTrajectory(@RequestParam(value = "imei", required = true) String imei, @RequestParam(value = "startTime", required = true) long startTime,
                                            @RequestParam(value = "endTime", required = true) long endTime, HttpServletRequest request) {
        logger.info("queryDeviceTrajectory,imei={},startTime={},endTime={}", imei, startTime, endTime);
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        ArrayList<String> imeis = new ArrayList<>();
        imeis.add(imei);
        Object validResult = validService.validImeiList(token, imeis);
        if (validResult instanceof RespCode) {
            return new RespEntity((RespCode) validResult);
        }
        if (imeis == null || imeis.size() == 0) {
            return new RespEntity(RespCode.PARAM_NOT_NULL);
        }
        List<LocationSubmeter> locationSubmeters = locationSubmeterService.queryLocationSubmeterByImeiAndTime(imei, startTime, endTime);
        if (locationSubmeters == null || locationSubmeters.size() == 0) {
            return new RespEntity(RespCode.NO_lOCATION_DATA_IS_AVAILABLE);
        }
        return new RespEntity(RespCode.SUCCESS, locationSubmeters);
    }

    /**
     * 恢复出厂设置
     * 设备不在线不发(恢复出厂设置指令不缓存,在线才发，顾直接下一条指令直接覆盖上一条指令)
     *
     * @param imei
     * @param request
     * @return
     */
    @ApiOperation(value = "恢复出厂设置")
    @PostMapping("/factoryDataReset")
    public ResponseEntity factoryDataReset(@RequestParam String imei, HttpServletRequest request) {
        logger.info("/factoryDataReset,body={}", imei);
        String token = request.getHeader(Constant.HEAD_TOKEN_KEY);
        ArrayList<String> imeis = new ArrayList<>();
        imeis.add(imei);
        Object validResult = validService.validImeiList(token, imeis);
        if (validResult instanceof RespCode) {
            return new ResponseEntity((RespCode) validResult, false, null);
        }
        if (!vcomDeviceInfoService.getDeviceOnline(imei)) {
            return new ResponseEntity(RespCode.DEVICE_OFF_LINE, false, null);
        }
        if (!vcomDeviceInfoService.getDeviceOnline(imei)) {
            return new ResponseEntity(RespCode.DEVICE_OFF_LINE, false, null);
        }
        RequestId requestId = requestRecordService.factoryDataReset(imei);
        return new ResponseEntity(RespCode.SUCCESS, requestId.isSuccess(), requestId.getRequestId());
    }

    @ApiOperation(value = "查询指令状态情况")
    @GetMapping("/getInstructionState")
    public RespEntity getInstructionState(@RequestParam("imei") String imei, @RequestParam("requestId") String requestId) {
        if (StringUtils.isBlank(imei) || StringUtils.isBlank(requestId)) {
            return new RespEntity(RespCode.PARAM_NOT_NULL);
        }
        VcomRequestRecord vcomRequestRecord = vcomDeviceInfoService.getInstructionState(imei, requestId);
        if (vcomRequestRecord==null){
            return new RespEntity(RespCode.NO_REQUEST);
        }
        VcomRequestVo vcomRequestVo = new VcomRequestVo();
        BeanUtils.copyProperties(vcomRequestRecord,vcomRequestVo);
        return new RespEntity(RespCode.SUCCESS, vcomRequestVo);
    }


}
